package com.barnett.tool;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

/**
 * TODO<拍照 图片库选择照片>
 * 
 * @author JiangJian
 * @data: 2014-6-4 上午10:29:48
 * @version: V1.0
 */
public class ChoosePhoto {
	/** 路径:应用包名 */
	String APP_PACKAGE;
	/** 路径:应用根目录 */
	private final String SDCARDROOT = Environment.getExternalStorageDirectory()
			.getAbsolutePath() + File.separator;
	/** 文件夹名称:软件根目录 */
	private String FOLDER_BASE;
	/** 用户下载图片保存的路径 */
	private String FOLDER_SDCARD_IMAGE = "image" + File.separator;
	/** 图片名 */
	private String FILENAME;
	/** 拍照 */
	public static final int PHOTOHRAPH = 1023;
	/** 缩放 */
	public static final int PHOTOZOOM = 1024;
	/** 结果 */
	public static final int PHOTORESOULT = 1025;

	public static final String IMAGE_UNSPECIFIED = "image/*";

	Activity activity;
	/** 要显示选择到的图片的ImageView */
	private ImageView imageView = null;
	/** 选择到的图片的uri */
	private Uri imguri = null;
	/** 选择到的图片的文件名 */
	private String filename = "";
	/** 手机内部存储路径 /data/data/ */
	private String systemDataPath = File.separator + "data" + File.separator
			+ "data" + File.separator;
	private String uploadImgPath = "";
	// 设置文件保存路径这里放在跟目录下
	File picture;

	/**
	 * 构造方法
	 * 
	 * @param FOLDER为根文件夹名称
	 */
	public ChoosePhoto(Activity activity, String FOLDER) {
		// TODO Auto-generated constructor stub
		this.activity = activity;
		this.FOLDER_BASE = FOLDER + File.separator;
		this.FILENAME = "tmp.jpeg";
		this.imageView = null;
		PackageInfo info = null;
		try {
			info = activity.getPackageManager().getPackageInfo(
					activity.getPackageName(), 0);
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
		}
		if (info != null) {

			APP_PACKAGE = info.packageName + File.separator;
		} else {
			APP_PACKAGE = "MyApp" + File.separator;
			Toast.makeText(activity,
					"未获取到应用包名,将图片存到默认的文件夹/data/data/MyApp/image中",
					Toast.LENGTH_SHORT).show();
		}
		systemDataPath = systemDataPath + APP_PACKAGE;
		CreatFile();
	}

	/**
	 * 构造方法
	 * 
	 * @param FOLDER为根文件夹名称
	 * @param imageView为要显示图片的view
	 */
	public ChoosePhoto(Activity activity, String FOLDER, ImageView imageView) {
		// TODO Auto-generated constructor stub
		this.activity = activity;
		this.FOLDER_BASE = FOLDER + File.separator;
		this.FILENAME = "tmp.jpeg";
		this.imageView = null;
		this.imageView = imageView;
		PackageInfo info = null;
		try {
			info = activity.getPackageManager().getPackageInfo(
					activity.getPackageName(), 0);
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
		}
		if (info != null) {
			APP_PACKAGE = info.packageName + File.separator;
		} else {
			APP_PACKAGE = "MyApp" + File.separator;
			Toast.makeText(activity,
					"未获取到应用包名,将图片存到默认的文件夹/data/data/MyApp/image中",
					Toast.LENGTH_SHORT).show();
		}
		CreatFile();
	}

	/**
	 * 删除对应图片文件
	 */
	public void DeleteFile(File file) {
		if (file != null) {
			file.delete();
		}
	}

	/**
	 * 清除所有图片文件
	 */
	public void ClearImage(ArrayList<File> fileList) {
		for (int i = 0; i < fileList.size(); i++) {
			fileList.get(i).delete();
		}
	}

	/**
	 * 打开系统内的照相机,并且指定存在指定文件夹下照片的name,在相应的ImageView显示出来
	 * 推荐传过来的图片名称为System.currentTimeMillis(), 即1970到现在的毫秒数,避免了图片名相同导致覆盖
	 */
	public void doTakePhoto(String filename, ImageView imageView) {
		this.imageView = null;
		FILENAME = filename + ".jpeg";
		this.imageView = imageView;
		doTakePhoto();
	}

	/**
	 * 打开系统内的照相机,并且指定存在指定文件夹下照片的name 推荐传过来的图片名称为System.currentTimeMillis(),
	 * 即1970到现在的毫秒数,避免了图片名相同导致覆盖
	 */
	public void doTakePhoto(String filename) {
		this.imageView = null;
		FILENAME = filename + ".jpeg";
		doTakePhoto();
	}

	/**
	 * 打开系统内的照相机拍照,存在指定文件夹下的照片名默认为tmp.jpeg 如果需求是上传多张图片,不可用此方法,由于图片名都为tmp.jpeg,
	 * 会覆盖掉以前图片
	 * 
	 * @param view
	 */
	public void doTakePhoto() {
		picture = new File(SDCARDROOT + FOLDER_BASE + FOLDER_SDCARD_IMAGE
				+ FILENAME);
		if (picture != null) {
			picture.delete();
		}
		Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		if (isSDCardAvailable()) {
			// 存在SD
			intent1.putExtra(
					MediaStore.EXTRA_OUTPUT,
					Uri.fromFile(new File(SDCARDROOT + FOLDER_BASE
							+ FOLDER_SDCARD_IMAGE, FILENAME)));
		} else {
			// 不存在SD卡
			intent1.putExtra(MediaStore.EXTRA_OUTPUT,
					Uri.fromFile(new File(systemDataPath, FILENAME)));
		}
		activity.startActivityForResult(intent1, PHOTOHRAPH);
	}

	/**
	 * 从系统内选择照片,并且指定存在指定文件夹下照片的name,在相应的ImageView显示出来
	 * 推荐传过来的图片名称为System.currentTimeMillis(), 即1970到现在的毫秒数,避免了图片名相同导致覆盖
	 * 
	 * @param view
	 */
	public void doChoosePhoto(String filename, ImageView imageView) {
		this.imageView = null;
		FILENAME = filename + ".jpeg";
		this.imageView = imageView;
		doChoosePhoto();
	}

	/**
	 * 从系统内选择照片,并且指定存在指定文件夹下照片的name, 推荐传过来的图片名称为System.currentTimeMillis(),
	 * 即1970到现在的毫秒数,避免了图片名相同导致覆盖
	 * 
	 * @param view
	 */
	public void doChoosePhoto(String filename) {
		this.imageView = null;
		FILENAME = filename + ".jpeg";
		doChoosePhoto();
	}

	/**
	 * 从系统内选择照片,存在指定文件夹下的照片名默认为tmp.jpeg, 如果需求是上传多张图片,不可用此方法,由于图片名都为tmp.jpeg,
	 * 会覆盖掉以前图片
	 * 
	 * @param view
	 */
	public void doChoosePhoto() {
		picture = new File(SDCARDROOT + FOLDER_BASE + FOLDER_SDCARD_IMAGE
				+ FILENAME);
		if (picture != null) {
			picture.delete();
		}
		Intent intent2 = new Intent(Intent.ACTION_PICK, null);
		intent2.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				IMAGE_UNSPECIFIED);
		activity.startActivityForResult(intent2, PHOTOZOOM);
	}

	/**
	 * 拍照上传或者从图片库中选照片之后必须调用该函数
	 * 
	 * @return ResultCallback
	 */
	public ResultCallback setCallback() {
		ResultCallback resultCallback = new ResultCallback() {
			@Override
			public HashMap<String, Object> getResult(int requestCode,
					int resultCode, Intent data) {
				// TODO Auto-generated method stub
				if (requestCode == PHOTOHRAPH) {
					// 如果sd卡存在
					if (isSDCardAvailable()) {
						// 处理没有选择拍照图片
						if (data != null) {
							if (data.getData() == null) {
								Toast.makeText(activity, "您没有拍照图片",
										Toast.LENGTH_SHORT).show();
								return null;
							}
						}
						// 设置文件保存路径这里放在跟目录下
						File picture = new File(SDCARDROOT + FOLDER_BASE
								+ FOLDER_SDCARD_IMAGE + FILENAME);

						if (picture.exists())
							imguri = Uri.fromFile(picture);
						else {
							imguri = null;
							Toast.makeText(activity, "您没有选择拍照图片",
									Toast.LENGTH_SHORT).show();
							return null;
						}
						filename = FILENAME;
					} else {
						// 不存在SD卡--->设置文件保存在安装目录下
						File picture = new File(systemDataPath + FILENAME);
						if (picture.exists())
							imguri = Uri.fromFile(picture);
						else {
							imguri = null;
							Toast.makeText(activity, "您没有选择拍照图片",
									Toast.LENGTH_SHORT).show();
							return null;
						}
						filename = FILENAME;
					}

				}
				/** 读取相册缩放图片 */
				if (requestCode == PHOTOZOOM) {
					if (data != null) {
						imguri = data.getData();
						filename = imguri.getPath().substring(
								imguri.getPath().lastIndexOf("/") + 1);
						String lowerFileName = filename.toLowerCase(Locale.US);
						Log.i("imguri", imguri.toString());
						if ((!lowerFileName.contains(".jpeg"))
								&& (!lowerFileName.contains("jpeg"))) {
							filename = FILENAME;
						}
					} else {
						Toast.makeText(activity, "您没有选择相册图片",
								Toast.LENGTH_SHORT).show();
						return null;
					}
				}

				if (imguri == null) {
					Toast.makeText(activity, "您没有选择图片", Toast.LENGTH_SHORT)
							.show();
					return null;
				}

				try {
					ContentResolver resolver = activity.getContentResolver();
					byte[] mContent;
					mContent = readStream(resolver.openInputStream(Uri
							.parse(imguri.toString())));
					BitmapFactory.Options options = new BitmapFactory.Options();
					options.inJustDecodeBounds = true;
					// 获取这个图片的宽和高
					Bitmap bitmap = BitmapFactory.decodeByteArray(mContent, 0,
							mContent.length, options); // 此时返回bm为空
					options.inJustDecodeBounds = false;
					options.inPreferredConfig = Config.RGB_565;// 降低图片从ARGB888到RGB565
					// 计算缩放比
					float be = (options.outWidth / (float) 320);
					if (be < 1.4)
						be = 1;
					options.inSampleSize = (int) be;
					// 重新读入图片，注意这次要把options.inJustDecodeBounds 设为 false哦
					bitmap = BitmapFactory.decodeByteArray(mContent, 0,
							mContent.length, options);
					bitmap = compressImage(bitmap);
					File file = null;
					if (!isSDCardAvailable()) {
						uploadImgPath = systemDataPath + FILENAME;
						file = new File(uploadImgPath);
						file.createNewFile();

						BufferedOutputStream bos = new BufferedOutputStream(
								new FileOutputStream(file));
						bitmap.compress(CompressFormat.JPEG, 100, bos);
						bos.flush();
						bos.close();
					} else {
						uploadImgPath = SDCARDROOT + FOLDER_BASE
								+ FOLDER_SDCARD_IMAGE + FILENAME;
						file = new File(uploadImgPath);
						file.createNewFile();
						BufferedOutputStream bos = new BufferedOutputStream(
								new FileOutputStream(file));
						bitmap.compress(CompressFormat.JPEG, 100, bos);
						bos.flush();
						bos.close();
					}
					if (bitmap != null) {
						bitmap = postRotateBitmap(uploadImgPath, bitmap);
						if (imageView != null) {
							imageView.setVisibility(View.VISIBLE);
							imageView.setImageBitmap(bitmap);
							imageView = null;
						} else {

						}
						HashMap<String, Object> fileInfo = new HashMap<String, Object>();
						fileInfo.put("filePath", uploadImgPath);
						fileInfo.put("file", file);
						fileInfo.put("bitmap", bitmap);
						return fileInfo;
					}

				} catch (Exception e) {
					// TODO Auto-generated catch block
					Log.i("Exception e", e.toString());
				}
				return null;
			}
		};
		return resultCallback;
	}

	/**
	 * 质量压缩
	 * 
	 * @param image
	 * @return
	 */
	public Bitmap compressImage(Bitmap image) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
		int options = 81;
		int longs = baos.toByteArray().length;
		while (options > 0 && longs / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
			baos.reset();// 重置baos即清空baos
			image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
			longs = baos.toByteArray().length;
			options -= 10;// 每次都减少10
		}
		ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
		Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
		return bitmap;
	}

	/**
	 * 检查SDCard是否存在，并且可以写入
	 */
	public boolean isSDCardAvailable() {
		return Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED);
	}

	/**
	 * 回调:把activity中的onActivityResult参数回调
	 * 
	 * @author 蒋健
	 */
	public interface ResultCallback {
		public HashMap<String, Object> getResult(int requestCode,
				int resultCode, Intent data);
	}

	/**
	 * 读取字节流
	 * 
	 * @param inStream
	 * @return
	 * @throws Exception
	 */
	public byte[] readStream(InputStream inStream) throws Exception {
		byte[] buffer = new byte[1024];
		int len = -1;
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		while ((len = inStream.read(buffer)) != -1) {
			outStream.write(buffer, 0, len);
		}
		byte[] data = outStream.toByteArray();
		outStream.close();
		inStream.close();
		return data;

	}

	/**
	 * 设置路径，如果没有该路径则创建
	 */
	private void CreatFile() {
		File file = new File(SDCARDROOT + FOLDER_BASE + FOLDER_SDCARD_IMAGE);
		if (!file.exists()) {

			try {
				// 按照指定的路径创建文件夹
				file.mkdirs();
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}

	/**
	 * 如果照片出现了 旋转 那么 就更改旋转度数
	 * 
	 * @param picUri
	 * @param photoViewBitmap
	 * @return
	 */
	public Bitmap postRotateBitmap(String picUri, Bitmap photoViewBitmap) {
		int angle = getExifOrientation(picUri);
		Log.i("picUri", "路径为->" + picUri + "旋转的角度->" + angle);
		if (angle != 0) { // 如果照片出现了 旋转 那么 就更改旋转度数
			Matrix matrix = new Matrix();
			matrix.postRotate(angle);
			photoViewBitmap = Bitmap.createBitmap(photoViewBitmap, 0, 0,
					photoViewBitmap.getWidth(), photoViewBitmap.getHeight(),
					matrix, true);
		}
		return photoViewBitmap;
	}

	/**
	 * 得到 图片旋转 的角度
	 * 
	 * @param filepath
	 * @return
	 */
	private int getExifOrientation(String filepath) {
		int degree = 0;
		ExifInterface exif = null;
		try {
			exif = new ExifInterface(filepath);
		} catch (IOException ex) {
			Log.e("test", "cannot read exif", ex);
		}
		if (exif != null) {
			int orientation = exif.getAttributeInt(
					ExifInterface.TAG_ORIENTATION, -1);
			if (orientation != -1) {
				switch (orientation) {
				case ExifInterface.ORIENTATION_ROTATE_90:
					degree = 90;
					break;
				case ExifInterface.ORIENTATION_ROTATE_180:
					degree = 180;
					break;
				case ExifInterface.ORIENTATION_ROTATE_270:
					degree = 270;
					break;
				}
			}
		}
		return degree;
	}
}
